<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>对局进行中...</title>
		<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
		<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.css" rel="stylesheet">
		<style>
			html {
				user-select: none;
				min-height: 750px;
				min-width: 1100px;
				height: 100%;
				background: #222;
			}
			body {
				height: 100%;
				margin: 0px;
			}

			.background-pattern {
				position: fixed;
				z-index: -1;
				top: -1000px;
				left: 0px;
				opacity: 0.2;
				font-size: 50px;
				white-space: nowrap;
				line-height: 115px;
				filter: contrast(1) brightness(1);
				transform-origin: center center;
				background-color: #222;
				animation:
					background-pattern-left-shift 1s cubic-bezier(0.165, 0.84, 0.44, 1) 0.7s forwards,
					background-pattern-reveal 0.75s linear 0.7s forwards;
			}
			@keyframes background-pattern-right-shift {
				0% {
					left: -600px;
					filter: contrast(1) brightness(1);
				}
				100% {
					left: 0px;
					filter: contrast(0.8) brightness(3);
				}
				}
			@keyframes background-pattern-left-shift {
				0% {
					left: 0px;
					filter: contrast(0.8) brightness(3);
				}
				100% {
					left: -600px;
					filter: contrast(1) brightness(1);
				}
			}
			@keyframes background-pattern-reveal {
				0% { opacity: 0; }
				100% { opacity: 0.2; }
				}
				.no-shifting-background-pattern { opacity: 0; }
				.right-shifting-background-pattern:not(.no-shifting-background-pattern) {
					animation: background-pattern-right-shift 1s cubic-bezier(0.165, 0.84, 0.44, 1) forwards;
			}
			.left-shifting-background-pattern:not(.no-shifting-background-pattern) {
				animation: background-pattern-left-shift 1s cubic-bezier(0.165, 0.84, 0.44, 1) forwards;
			}

			.chessboard-border {
				z-index: 1;
				align-self: flex-end;
				margin-bottom: 25px;
				transform: scale(0.915);
				transform-origin: center center;
				width: 600px;
				height: 600px;
				border: 20px solid #FFFD;
				filter: drop-shadow(#FFF8 0px 0px 8px);
				animation: chessboard-reveal 0.5s ease-out 0s;
				backdrop-filter: blur(5px);
			}
			@keyframes chessboard-reveal {
				0% {
					background-color: white;
					transform: scale(0.0);
					opacity: 0;
				}
				40% {
					background-color: white;
					transform: scale(0.95);
					opacity: 0.5;
				}
				60% {
					background-color: #FFF6;
					transform: scale(0.95);
					opacity: 1.0;
				}
				100% {
					transform: scale(0.915);
					opacity: 1.0;
				}
			}
			.chessboard-grid {
				width: 550px;
				height: 550px;
				margin: 21px;
				border: 4px solid darkgray;
				background:
					repeating-linear-gradient(90deg, #FFF4 0%, #FFF4 0.3571%, #FFF1 0.3571%, #FFF0 3.5714%, #FFF1 6.7857%, #FFF4 6.7857%, #FFF4 7.1429%),
					repeating-linear-gradient(0deg, #FFF4 0%, #FFF4 0.3571%, #FFF1 0.3571%, #FFF0 3.5714%, #FFF1 6.7857%, #FFF4 6.7857%, #FFF4 7.1429%);
			}
			.chessboard-row {
				display: flex;
				position: relative;
				top: -596px;
				left: 3px;
			}

			.chess-piece {
				position: relative;
				margin: 5.75px;
				min-width: 28px;
				min-height: 28px;
				border-radius: 14px;
				box-sizing: border-box;
			}
			.chess-piece-white {
				background-color: white;
				filter: drop-shadow(#0008 0px 0px 3px);
			}
			.chess-piece-black {
				background-color: black;
				filter: drop-shadow(#FFF8 0px 0px 3px);
			}
			.chess-piece-white-winner { border: 5px solid #F88; }
			.chess-piece-black-winner { border: 5px solid #8CF; }
			.chess-piece-enabled:not(.chess-piece-black):not(.chess-piece-white):hover { background: #8888; }

			.top-game-bar {
				z-index: 1;
				display: flex;
				justify-content: center;
				align-items: center;
				position: absolute;
				top: -60px;
				height: 60px;
				min-width: 1100px;
				width: 100%;
				background-color: #444;
				filter: drop-shadow(#0008 0px 0px 20px);
				animation: game-bar-reveal 0.15s ease-in 0.5s forwards;
			}
			@keyframes game-bar-reveal {
				0% { top: -60px; }
				100% { top: 0px; }
			}
			.game-timer {
				font-family: Impact;
				text-align: center;
				width: 100px;
				margin: 0px 20px;
			}
			.game-timer-main {
				font-size: 40px;
				color: white;
				filter: drop-shadow(white 0px 0px 8px);
			}
			.game-timer-side {
				font-size: 30px;
				color: #777;
				filter: drop-shadow(#777 0px 0px 8px);
			}
			.updateing-game-timer { animation: game-timer-update 0.125s ease-out alternate 2; }
			@keyframes game-timer-update {
				0% { transform: scale(1); }
				100% {
					transform: scale(1.2);
					color: white;
				}
			}

			.chessing-panel {
				width: 100%;
				height: 100%;
				display: flex;
				justify-content: space-between;
			}

			.gamer-panel {
				display: flex;
				flex-direction: column;
				align-items: center;
				background-color: #333;
				padding-top: 60px;
				width: 250px;
				filter: drop-shadow(#0008 0px 0px 20px);
			}
			.gamer-panel-black {
				transform: translate(-250px, 0px);
				background: linear-gradient(90deg, #333 80%, #444 100%);
				animation: gamer-panel-reveal-left 0.25s cubic-bezier(0.165, 0.84, 0.44, 1) 0.75s forwards;
			}
			@keyframes gamer-panel-reveal-left {
				0% { transform: translate(-250px, 0px); }
				100% { transform: translate(0px, 0px); }
			}
			.gamer-panel-white {
				visibility: hidden;
				background: linear-gradient(270deg, #333 80%, #444 100%);
				animation: gamer-panel-reveal-right 0.25s cubic-bezier(0.165, 0.84, 0.44, 1) 0.75s forwards;
			}
			@keyframes gamer-panel-reveal-right {
				0% { visibility: visible; transform: translate(250px, 0px); }
				100% { visibility: visible; transform: translate(0px, 0px); }
			}
			.player-info {
				margin: 12px 6px 6px 6px;
				padding: 4px;
				color: #EEE;
				background-color: #DDD3;
				font-size: 20px;
				font-weight: bold;
				white-space: nowrap;
				box-sizing: border-box;
				width: calc(100% - 18px);
				min-height: 38px;
				overflow: hidden;
				text-overflow: ellipsis;
				border: #777 1px solid;
				border-radius: 10px;
			}
			.player-info::before {
				content: attr(icon);
				margin-right: 5px;
				filter: drop-shadow(#FFF 0px 0px 20px);
			}

			.player-profile-panel {
				margin: 6px;
				padding: 5px;
				box-sizing: border-box;
				text-align: justify;
				font-weight: lighter;
				font-size: 15px;
				color: #666;
				width: calc(100% - 18px);
				background-color: #0003;
				border: #444 1px solid;
				box-shadow: inset #0008 0px 0px 10px;
				border-radius: 10px;
			}
			.player-profile-quote {
				font-weight: bold;
				font-family:'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
				font-size: 40px;
				display: inline-block;
				height: 25px;
				overflow: hidden;
				margin-right: 5px;
			}
			.player-stats-panel {
				margin: 6px;
				padding: 8px 0px;
				display: flex;
				flex-direction: column;
				width: calc(100% - 20px);
				background-color: #0003;
				border: #444 1px solid;
				box-shadow: inset #0008 0px 0px 10px;
				border-radius: 10px;
			}
			.player-stat-icon {
				margin: 0px 10px;
				width: 20px;
			}
			.player-stat {
				color: #AAA;
				margin: 8px 12px;
				height: 30px;
				display: flex;
				flex-direction: row;
				align-items: center;
				background-color: #444;
				border: #555 1px solid;
				border-radius: 5px;
			}
			.player-message-panel {
				margin: 6px 6px 12px 6px;
				display: flex;
				padding-top: 5px;
				flex-direction: column;
				justify-content: space-between;
				align-items: center;
				flex-grow: 1;
				width: calc(100% - 20px);
				height: 300px;
				background-color: #0006;
				border: #555 1px solid;
				box-shadow: inset #0008 0px 0px 10px;
				border-radius: 10px;
			}
			.player-message-list {
				display: flex;
				flex-direction: column;
				justify-content: flex-end;
				align-items: center;
				overflow: hidden;
				width: 100%;
			}
			.player-message-time {
				color: #444;
				font-size: 13px;
				margin: 0px 0px -5px 0px;
				animation: message-slide-out 0.4s ease-in forwards;
			}
			.player-message {
				color: #888;
				text-align: justify;
				text-indent: 8px;
				padding: 5px 0px;
				width: calc(100% - 20px);
				background-color: #2B2B2B;
				border: #444 1px solid;
				margin: 10px;
				border-radius: 5px;
				animation: message-slide-out 0.4s ease-in forwards;
			}
			.hidden-message-list { visibility: collapse; }
			@keyframes message-slide-out {
				0% { transform: translate(-300px, 0px); }
				40% { filter: brightness(3); }
				100% { transform: translate(0px, 0px); }
			}
			.player-message-options {
				padding: 5px 0px;
				width: calc(100% - 20px);
				margin: 10px;
				display: flex;
				justify-content: space-between;
			}
			.player-message-editor {
				outline: none;
				padding-left: 8px;
				color: #AAA;
				height: 30px;
				width: calc(100% - 50px);
				background-color: #222;
				border: #555 1px solid;
				border-radius: 4px;
			}
			.player-message-button {
				display: flex;
				justify-content: center;
				align-items: center;
				width: 30px;
				height: 30px;
				color: #888;
				background-color: #333;
				border: #555 1px solid;
				border-radius: 4px;
			}
			.player-message-button:hover { background-color: #555; }
			.player-message-button:active { background-color: #2B2B2B; }

			.popup-panel {
				z-index: 128;
				position: fixed;
				top: 0px;
				left: 0px;
				min-width: 1100px;
				width: 100%;
				height: 100%;
				background-color: #0008;
				backdrop-filter: blur(20px);
				animation: popup-reveal 0.2s linear forwards;
			}
			@keyframes popup-reveal {
				0% { opacity: 0; }
				100% { opacity: 1; }
			}
			.popup-panel-hiding { animation: popup-panel-fade-out 0.1s linear forwards; }
			@keyframes popup-panel-fade-out { 100% { opacity: 0; } }
			.popup-panel-revealing { animation: popup-panel-fade-in 0.1s linear forwards; }
			@keyframes popup-panel-fade-in {
				0% { opacity: 0; }
				100% { opacity: 1; }
			}

			.game-over-panel {
				height: 100%;
				margin-top: -25px;
				display: flex;
				flex-direction: column;
				justify-content: center;
				align-items: center;
			}
			.horizontal-separator {
				filter: drop-shadow(#FFFF 0px 0px 15px);
				width: 0px;
				height: 10px;
				margin-bottom: -10px;
				background-color: white;
				animation: horizontal-separator-reveal 0.5s cubic-bezier(0.165, 0.84, 0.44, 1) 0.25s forwards;
			}
			@keyframes horizontal-separator-reveal {
				0% { width: 0px; }
				100% { width: 600px; }
			}
			.popup-panel .game-over-title {
				filter: drop-shadow(#FFF8 0px 0px 10px);
				color: white;
				font-weight: bolder;
				font-size: 90px;
				height: 0px;
				overflow: hidden;
				animation: game-over-title-reveal 0.5s cubic-bezier(0.165, 0.84, 0.44, 1) 0.75s forwards;
			}
			@keyframes game-over-title-reveal {
				0% { height: 0px; }
				100% { height: 115px; }
			}
			.game-over-panel-below-separator {
				height: 0px;
				overflow: hidden;
				animation: game-over-panel-below-separator-reveal 0.5s cubic-bezier(0.165, 0.84, 0.44, 1) 0.75s forwards;
			}
			@keyframes game-over-panel-below-separator-reveal {
				0% { height: 0px; }
				100% { height: 405px; }
			}
			.game-result-stats {
				display: flex;
				flex-direction: row;
			}
			.game-result-stats-card {
				width: 250px;
				height: 300px;
				margin: 30px 10px 10px 10px;
				backdrop-filter: blur(8px);
				filter: drop-shadow(#FFF2 0px 0px 10px);
				border: 1px solid #FFF2;
				border-radius: 10px;
				font-size: 16px;
				font-weight: bold;
				color: #AAA;
				display: flex;
				flex-direction: column;
				align-items: flex-start;
				justify-content: space-around;
			}
			.game-result-stats-card-black { background: linear-gradient(45deg, #FFF2, #FFF1); }
			.game-result-stats-card-white { background: linear-gradient(45deg, #FFF5, #FFF2); }
			.game-result-stats-item {
				width: 220px;
				margin: 0px 10px 0px 30px;
				white-space: nowrap;
				overflow: hidden;
				text-overflow: ellipsis;
				filter: drop-shadow(#EEE8 0px 0px 10px);
			}
			.game-result-gamer-name {
				cursor: pointer;
				color: #EEE;
				font-size: 24px;
				margin-left: 12px;
			}
			.game-result-winner {
				font-size: 40px;
				margin: 0px 20px 8px 0px;
				font-weight: bolder;
				align-self: flex-end;
				width: 70px;
				height: 70px;
				box-sizing: border-box;
				border-radius: 35px;
				padding-bottom: 5px;
				display: flex;
				justify-content: center;
				align-items: center;
				border: #FFF2 1px solid;
				background-color: #FFF2;
				color: #444;
				filter: drop-shadow(#8888 0px 0px 10px);
			}
			.game-result-winner-red {
				color: #F99;
				filter: drop-shadow(#F88 0px 0px 10px);
			}
			.game-result-winner-blue {
				color: #8CF;
				filter: drop-shadow(#8CF 0px 0px 10px);
			}

			.game-over-buttons {
				display: flex;
				flex-direction: row;
				justify-content: space-between;
				cursor: pointer;
			}
			.game-over-button {
				display: flex;
				align-items: center;
				justify-content: center;
				background-color: #FFF3;
				border: #FFF3 1px solid;
				border-radius: 10px;
				filter: drop-shadow(#FFF8 0px 0px 5px);
				color: white;
				margin: 10px;
				width: 150px;
				height: 35px;
			}
			.game-over-button:hover { background-color: #FFF5; }
			.game-over-button:active { background-color: #FFF4; }
		</style>
	</head>
	<body>
		<div class="background-pattern no-shifting-background-pattern left-shifting-background-pattern">
		<script>
			for (let i = 0; i < 29; ++i) {
				for (let j = 0; j < 22; ++j)
					document.write("⚫　");
				document.write("<br/>");
			}
		</script>
		</div>

		<div class="top-game-bar">
			<div class="game-timer game-timer-side game-timer-left-side">00:00</div>
			<!-- <div class="game-timer game-timer-main">- - : - -</div> -->
			<div class="game-timer game-timer-main">READY</div>
			<div class="game-timer game-timer-side game-timer-right-side">00:00</div>
		</div>

		<div class="chessing-panel">
			<div class="gamer-panel gamer-panel-black">
				<div class="player-info" id="BlackNicknameLabel" icon="⚫">--</div>
				<div class="player-profile-panel" id="BlackProfileLabel">
					<div class="player-profile-quote">“</div>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
				</div>
				<div class="player-stats-panel">
					<div class="player-stat">
						<div class="player-stat-icon fa-solid fa-chart-simple fa-lg"></div>
						<div id="BlackScoreLabel">积分：--</div>
					</div>
					<div class="player-stat">
						<div class="player-stat-icon fa-solid fa-chart-pie fa-lg"></div>
						<div id="BlackWinGamesLabel">胜局：--/--</div>
					</div>
					<div class="player-stat">
						<div class="player-stat-icon fa-solid fa-percent fa-lg" style="margin: 0px 5px 0px 15px;"></div>
						<div id="BlackWinsRatioLabel">胜率：--%</div>
					</div>
				</div>
				<div class="player-message-panel player-message-panel-sendable">
					<div style="flex-grow: 1;"></div>
					<div class="player-message-list" id="BlackMessagesList"></div>
					<div class="player-message-options" id="BlackMessageOptions"></div>
				</div>
			</div>

			<div class="chessboard-border">
				<div class="chessboard-grid"></div>
				<script>
					for (let x = 0; x < 15; ++x) {
						document.write(`<div class="chessboard-row">`);
						for (let y = 0; y < 15; ++y)
							document.write(`<div class="chess-piece" coord="${x + "," + y}"></div>`);
						document.write(`</div>`);
					}
				</script>
			</div>

			<div class="gamer-panel gamer-panel-white">
				<div class="player-info" id="WhiteNicknameLabel" icon="⚪">--</div>
				<div class="player-profile-panel" id="WhiteProfileLabel">
					<div class="player-profile-quote">“</div>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
				</div>
				<div class="player-stats-panel">
					<div class="player-stat">
						<div class="player-stat-icon fa-solid fa-chart-simple fa-lg"></div>
						<div id="WhiteScoreLabel">积分：--</div>
					</div>
					<div class="player-stat">
						<div class="player-stat-icon fa-solid fa-chart-pie fa-lg"></div>
						<div id="WhiteWinGamesLabel">胜局：--/--</div>
					</div>
					<div class="player-stat">
						<div class="player-stat-icon fa-solid fa-percent fa-lg" style="margin: 0px 5px 0px 15px;"></div>
						<div id="WhiteWinsRatioLabel">胜率：--%</div>
					</div>
				</div>
				<div class="player-message-panel player-message-panel-sendable">
					<div style="flex-grow: 1;"></div>
					<div class="player-message-list" id="WhiteMessagesList"></div>
					<div class="player-message-options" id="WhiteMessageOptions"></div>
				</div>
			</div>
		</div>

		<div class="game-over-popup-panel popup-panel-revealing" hidden>
		<!-- <div class="game-over-popup-panel popup-panel"> -->
			<div class="game-over-panel">
				<div class="game-over-title">对局结束</div>
				<div class="horizontal-separator"></div>
				<div class="game-over-panel-below-separator">
					<div class="game-result-stats" id="GameResultCards">
						<div class="game-result-stats-card game-result-stats-card-black">
							<div id="BlackNicknameResultLabel" class="game-result-stats-item game-result-gamer-name" user-id="0">⚫ --</div>
							<div class="game-result-stats-item">本局各项统计信息如下：</div>
							<div id="BlackDurationResultLabel" class="game-result-stats-item" title="棋手耗时">● 棋手耗时：--分--秒</div>
							<div id="BlackScoreResultLabel" class="game-result-stats-item" title="积分变化">● 积分变化：--点（--点）</div>
							<div id="BlackRateResultLabel" class="game-result-stats-item" title="近期胜率变化">● 胜率变化：--%（--%）</div>
							<div id="BlackResultLabel" class="game-result-winner">无</div>
						</div>
						<div class="game-result-stats-card game-result-stats-card-white">
							<div id="WhiteNicknameResultLabel" class="game-result-stats-item game-result-gamer-name" user-id="0">⚪ --</div>
							<div class="game-result-stats-item">本局各项统计信息如下：</div>
							<div id="WhiteDurationResultLabel" class="game-result-stats-item" title="棋手耗时">● 棋手耗时：--分--秒</div>
							<div id="WhiteScoreResultLabel" class="game-result-stats-item" title="积分变化">● 积分变化：--点（--点）</div>
							<div id="WhiteRateResultLabel" class="game-result-stats-item" title="近期胜率变化">● 胜率变化：--%（--%）</div>
							<div id="WhiteResultLabel" class="game-result-winner">无</div>
						</div>
					</div>
					<div class="game-over-buttons">
						<div class="game-over-button review-chessboard-button">查看局面</div>
						<div class="game-over-button new-game-button" id="NewGameButton">新的对局</div>
						<div class="game-over-button return-button" id="ReturnMainPageButton">返回大厅</div>
					</div>
				</div>
				<div class="horizontal-separator"></div>
			</div>
		</div>

		<script>
			let IPv4 = "10.107.116.17";
			let UserID = parseInt(sessionStorage.getItem("CurrentUser"));
			let BlackID = 0, WhiteID = 0;
			let BlackUser = null, WhiteUser = null;
			let LocalID = 0, RemoteID = 0;
			let UserColor = "";
			let PiecesCount = 0;
			for (let Attribute of window.location.href.split("?")[1].split("&"))
				if (Attribute.startsWith("black_id="))
					BlackID = parseInt(Attribute.slice(9));
				else if (Attribute.startsWith("white_id="))
					WhiteID = parseInt(Attribute.slice(9));

			if (UserID == BlackID) {
				UserColor = "black";
				LocalID = BlackID;
				RemoteID = WhiteID;
				$("#WhiteMessagesList").addClass("hideable-message-list");
				BlackMessageOptions.innerHTML = `
					<input class="player-message-editor" id="MessageEditBox" maxlength="30" placeholder="编辑消息（不超过30字）"/>
					<div></div>
					<div class="player-message-button fa-solid fa-paper-plane" id="MessageSendButton" title="发送消息"></div>
				`;
				WhiteMessageOptions.innerHTML = `
					<div></div>
					<div class="player-message-button fa-solid fa-eye" id="ScreenMessagesButton" title="屏蔽消息/取消屏蔽"></div>
				`;
			}
			else {
				UserColor = "white";
				LocalID = WhiteID;
				RemoteID = BlackID;
				$("#BlackMessagesList").addClass("hideable-message-list");
				WhiteMessageOptions.innerHTML = `
					<input class="player-message-editor" id="MessageEditBox" maxlength="30" placeholder="编辑消息（不超过30字）"/>
					<div></div>
					<div class="player-message-button fa-solid fa-paper-plane" id="MessageSendButton" title="发送消息"></div>
				`;
				BlackMessageOptions.innerHTML = `
					<div></div>
					<div class="player-message-button fa-solid fa-eye" id="ScreenMessagesButton" title="屏蔽消息/取消屏蔽"></div>
				`;
			}
			$.post("/Gomokult_war_exploded/servlet/GetUserByIDServlet", {
				userID: BlackID,
			}, (data) => {
				BlackUser = JSON.parse(data);
				BlackNicknameLabel.innerHTML = `${BlackUser.nickname}`;
				BlackProfileLabel.innerHTML = `<div class="player-profile-quote">“</div>${BlackUser.profile}`;
				BlackScoreLabel.innerHTML = `${BlackUser.score}`;
				BlackWinGamesLabel.innerHTML = `${BlackUser.winGames}/${BlackUser.totalGames}`;
				BlackWinsRatioLabel.innerHTML = `${BlackUser.totalGames == 0 ? "50.00" : (100 * BlackUser.winGames / BlackUser.totalGames).toFixed(2)}%`;
			});
			$.post("/Gomokult_war_exploded/servlet/GetUserByIDServlet", {
				userID: WhiteID,
			}, (data) => {
				WhiteUser = JSON.parse(data);
				WhiteNicknameLabel.innerHTML = `${WhiteUser.nickname}`;
				WhiteProfileLabel.innerHTML = `<div class="player-profile-quote">“</div>${WhiteUser.profile}`;
				WhiteScoreLabel.innerHTML = `${WhiteUser.score}`;
				WhiteWinGamesLabel.innerHTML = `${WhiteUser.winGames}/${WhiteUser.totalGames}`;
				WhiteWinsRatioLabel.innerHTML = `${WhiteUser.totalGames == 0 ? "50.00" : (100 * WhiteUser.winGames / WhiteUser.totalGames).toFixed(2)}%`;
			});

			let Socket = new WebSocket(`ws://${IPv4}:8080/Gomokult_war_exploded/websocket/${LocalID}`);
			window.onbeforeunload = () => { Socket.close(); }
			function SocketSend(message_object) {
				let Data = {
					SendName: LocalID,
					RecevieName: RemoteID,
					message: JSON.stringify(message_object)
				};
				Socket.send(JSON.stringify(Data));
			}
			function SendChat(timestamp, content) {
				let Message = {
					type: "chat",
					timestamp: timestamp,
					content: content
				};
				SocketSend(Message);
			}
			function SendPiece(x, y, duration) {
				let Message = {
					type: "piece",
					async: duration,
					x: x,
					y: y
				};
				SocketSend(Message);
			}

			const CensoredWords = ["傻卵", "龟孙", "软蛋", "瘪三", "婊子", "王八", "憨逼", "憨批", "愣子", "傻子", "傻鸟", "吃屎", "去死", "自杀", "傻逼", "二逼", "傻狗", "菜逼", "菜鸡", "你妈", "鸡巴", "JB", "2B", "傻", "操", "屎", "尿", "屌", "屄"];
			function FilterMessage(message) {
				for (let CensoredWord of CensoredWords)
					message = message.replace(CensoredWord, "*".repeat(CensoredWord.length));
				return message;
			}
			ScreenMessagesButton.onclick = () => {
				let SelectedButton = $("#ScreenMessagesButton");
				SelectedButton.toggleClass("fa-eye-slash");
				SelectedButton.toggleClass("fa-eye");
				$(".hideable-message-list").toggleClass("hidden-message-list");
			};

			function FormatPositives(number) { return (number < 0 ? "" : "+") + number; }
			function FormatDuration(duration) { return `${Math.floor(duration / 60)}分${Math.floor(duration % 60)}秒`; }
			function FormatDate(date) {
				let Year = date.getFullYear();
				let Month = (date.getMonth() < 9 ? "0" : "") + (date.getMonth() + 1);
				let Date = (date.getDate() < 10 ? "0" : "") + date.getDate();
				let Hours = (date.getHours() < 10 ? "0" : "") + date.getHours();
				let Minutes = (date.getMinutes() < 10 ? "0" : "") + date.getMinutes();
				return `${Year}-${Month}-${Date} ${Hours}:${Minutes}`;
			}
			function OutputMessage(list, timestamp, content) {
				list.innerHTML += `
					<div class="player-message-time">${FormatDate(new Date(timestamp))}</div>
					<div class="player-message">${content}</div>
				`;
			}
			MessageSendButton.onclick = () => {
				let Timestamp = new Date().getTime();
				let Content = FilterMessage(MessageEditBox.value);
				MessageEditBox.value = "";
				if (UserColor == "black")
					OutputMessage(BlackMessagesList, Timestamp, Content);
				else
					OutputMessage(WhiteMessagesList, Timestamp, Content);
				SendChat(Timestamp, Content);
			}

			let LastTimestamp = StartTimestamp = new Date().getTime() + 1700, BlackTimer = 0, WhiteTimer = 0;
			function FormatMilliseconds(time) {
				time = Math.floor(time / 1000);
				Minutes = Math.floor(time / 60);
				Seconds = Math.floor(time % 60);
				return (Minutes >= 10 ? "" : "0") + Minutes + ":" + (Seconds >= 10 ? "" : "0") + Seconds;
			}
			function UpdateTimer(timer_class, time) {
				$(`.game-timer-${timer_class}`).addClass("updateing-game-timer");
				setTimeout(() => { $(`.game-timer-${timer_class}`).removeClass("updateing-game-timer"); }, 250);
				setTimeout(() => { $(`.game-timer-${timer_class}`).html(time); }, 25);
			}
			
			let RoundDuration = 31, CountdownTimerID = 0;
			setTimeout(() => {
				CountdownTimerID = setInterval(() => {
					if (RoundDuration > 0) {
						--RoundDuration;
						if (RoundDuration <= 10) {
							$(".game-timer-main").css("color", "#F66");
							$(".game-timer-main").css("filter", "drop-shadow(#F66 0px 0px 8px)");
						}
						UpdateTimer("main", "00:" + (RoundDuration >= 10 ? "" : "0") + RoundDuration);
					}
					else
						GameOver(PiecesCount % 2 == 0 ? "White" : "Black");
				}, 1000);
			}, 750);
			setTimeout(() => {
				if (UserColor == "black")
					$(".chess-piece").addClass("chess-piece-enabled");
			}, 1750);
			
			let PiecesSequence = [];
			function EncodeSequence(piece_sequence) {
				let Data = new Uint8Array(piece_sequence.length);
				for (let i = 0; i < piece_sequence.length; ++i)
					Data[i] = (piece_sequence[i][0] << 4) + piece_sequence[i][1];
				return new TextDecoder().decode(Data);
			}

			function ResetChess() {
				PiecesCount = 0;
				// $(`.chess-piece`).addClass("chess-piece-enabled");
				for (let Class of ["black", "white", "black-winner", "white-winner"])
					$(`.chess-piece`).removeClass("chess-piece-" + Class);
			}
			function GameOver(winner) {
				// console.log(EncodeSequence(PiecesSequence));

				let Winner = winner.toLowerCase();
				let BlackScoreDelta = 0, WhiteScoreDelta = 0;
				if (Winner == "black") {
					BlackScoreDelta = 20;
					WhiteScoreDelta = -10;
				}
				else if (Winner == "white") {
					BlackScoreDelta = -10;
					WhiteScoreDelta = 20;
				}
				else {
					BlackScoreDelta = 10;
					WhiteScoreDelta = 10;
				}
				if (Winner == UserColor || (Winner == "draw" && UserColor == "black")) {
					$.post("/Gomokult_war_exploded/servlet/CountGameScoreServlet", {
						userID: BlackID,
						deltaScore: BlackScoreDelta
					}, (data) => {});
					$.post("/Gomokult_war_exploded/servlet/CountGameScoreServlet", {
						userID: WhiteID,
						deltaScore: WhiteScoreDelta
					}, (data) => {});

					$.post("/Gomokult_war_exploded/servlet/SubmitGameDataServlet", {
						userBlack: BlackID,
						userWhite: WhiteID,
						winner: Winner,
						piecesSequence: EncodeSequence(PiecesSequence),
						date: StartTimestamp,
						blackDuration: Math.ceil(BlackTimer / 1000),
						whiteDuration: Math.ceil(WhiteTimer / 1000),
						blackCounting: `${BlackUser.score + BlackScoreDelta}点（${FormatPositives(BlackScoreDelta)}点）`,
						whiteCounting: `${WhiteUser.score + WhiteScoreDelta}点（${FormatPositives(WhiteScoreDelta)}点）`
					}, (data) => {});
				}

				let BlackResultMapping = {"black": "胜", "white": "负", "draw": "平"};
				let BlackWinsRatioOld = BlackUser.winGames / BlackUser.totalGames;
				let BlackWinsRatio = (BlackUser.winGames + (Winner == "black")) / (BlackUser.totalGames + 1);
				let BlackWinsRatioDelta = BlackWinsRatio - BlackWinsRatioOld;
				BlackNicknameResultLabel.innerHTML = `⚫ ${BlackUser.nickname}`;
				BlackDurationResultLabel.innerHTML = `● 棋手耗时：${FormatDuration(Math.ceil(BlackTimer / 1000))}`;
				BlackScoreResultLabel.innerHTML = `● 积分变化：${BlackUser.score + BlackScoreDelta}点（${FormatPositives(BlackScoreDelta)}点）`;
				BlackRateResultLabel.innerHTML = `● 胜率变化：${(100 * BlackWinsRatio).toFixed(2)}%（${(BlackWinsRatioDelta < 0 ? "" : "+") + (100 * BlackWinsRatioDelta).toFixed(2)}%）`;
				BlackResultLabel.innerHTML = BlackResultMapping[Winner];
				if (Winner == "black")
					$("#BlackResultLabel").addClass("game-result-winner-blue");

				let WhiteResultMapping = {"white": "胜", "black": "负", "draw": "平"};
				let WhiteWinsRatioOld = WhiteUser.winGames / WhiteUser.totalGames;
				let WhiteWinsRatio = (WhiteUser.winGames + (Winner == "white")) / (WhiteUser.totalGames + 1);
				let WhiteWinsRatioDelta = WhiteWinsRatio - WhiteWinsRatioOld;
				WhiteNicknameResultLabel.innerHTML = `⚪ ${WhiteUser.nickname}`;
				WhiteDurationResultLabel.innerHTML = `● 棋手耗时：${FormatDuration(Math.ceil(WhiteTimer / 1000))}`;
				WhiteScoreResultLabel.innerHTML = `● 积分变化：${WhiteUser.score + WhiteScoreDelta}点（${FormatPositives(WhiteScoreDelta)}点）`;
				WhiteRateResultLabel.innerHTML = `● 胜率变化：${(100 * WhiteWinsRatio).toFixed(2)}%（${(WhiteWinsRatioDelta < 0 ? "" : "+") + (100 * WhiteWinsRatioDelta).toFixed(2)}%）`;
				WhiteResultLabel.innerHTML = WhiteResultMapping[Winner];
				if (Winner == "white")
					$("#WhiteResultLabel").addClass("game-result-winner-red");

				$(".chess-piece").removeClass("chess-piece-enabled");
				clearInterval(CountdownTimerID);
				setTimeout(() => {
					$(".game-over-popup-panel").removeAttr("hidden");
					$(".game-over-popup-panel").addClass("popup-panel");
				}, 1000);
			}
			function FreezeChessboard() { $(`.chess-piece`).removeClass("chess-piece-enabled"); }
			function ResumeChessboard() { $(`.chess-piece`).addClass("chess-piece-enabled"); }
			function SwitchingDrop(x, y) {
				let TargetPiece = $(`.chess-piece[coord="${x + "," + y}"]`);
				if (TargetPiece.hasClass("chess-piece-black") || TargetPiece.hasClass("chess-piece-white"))
					return false;
				TargetPiece.addClass(`chess-piece-${++PiecesCount & 1 ? "black" : "white"}`);
				$(".background-pattern").removeClass("no-shifting-background-pattern");
				$(".background-pattern").toggleClass("left-shifting-background-pattern");
				$(".background-pattern").toggleClass("right-shifting-background-pattern");
				PiecesSequence.push([x, y]);
				RoundDuration = 30;
				$(".game-timer-main").css("color", "#FFF");
				$(".game-timer-main").css("filter", "drop-shadow(#FFF 0px 0px 8px)");
				UpdateTimer("main", "00:30");
				return true;
			}
			function PieceWeight(x, y) {
				let TargetPiece = $(`.chess-piece[coord="${x + "," + y}"]`);
				if (TargetPiece.hasClass("chess-piece-black"))
					return 1;
				if (TargetPiece.hasClass("chess-piece-white"))
					return -1;
				return 0;
			}
			const Biases = [[-4, 0, 1, 0], [-4, -4, 1, 1], [0, -4, 0, 1], [4, -4, -1, 1]]
			function WinnerCheck(x, y) {
				for (let Bias of Biases)
					for (let i = x + Bias[0], j = y + Bias[1], k = 0; k < 5; i += Bias[2], j += Bias[3], ++k) {
						let WeightSum = 0;
						for (let t = 0; t < 5; ++t)
							WeightSum += PieceWeight(i + t * Bias[2], j + t * Bias[3]);
						if (Math.abs(WeightSum) >= 5) {
							Winner = WeightSum > 0 ? "Black" : "White";
							for (let t = 0, m = i, n = j; t < 5; ++t, m += Bias[2], n += Bias[3])
								$(`.chess-piece[coord="${m},${n}"]`).addClass(`chess-piece-${Winner.toLowerCase()}-winner`);
							return Winner;
						}
					}
				if (PiecesCount >= 225)
					return "Draw";
				return "None";
			}
			$(".chess-piece").click((event) => {
				if (!event.target.classList.contains("chess-piece-enabled"))
					return;
				FreezeChessboard();
				let Coordinate = event.target.getAttribute("coord").split(",");
				let x = parseInt(Coordinate[0]);
				let y = parseInt(Coordinate[1]);
				
				if (UserColor == "black") {
					BlackTimer += new Date() - LastTimestamp;
					UpdateTimer("left-side", FormatMilliseconds(BlackTimer));
				}
				else {
					WhiteTimer += new Date() - LastTimestamp;
					UpdateTimer("right-side", FormatMilliseconds(WhiteTimer));
				}

				SwitchingDrop(x, y);
				SendPiece(x, y, UserColor == "black" ? BlackTimer : WhiteTimer);

				let Winner = WinnerCheck(x, y);
				if (Winner != "None")
					GameOver(Winner);
			});
			
			Socket.onmessage = (event) => {
				let Message = JSON.parse(JSON.parse(event.data).message);
				if (Message.type == "chat")
					if (UserColor == "black")
						OutputMessage(WhiteMessagesList, Message.timestamp, Message.content);
					else
						OutputMessage(BlackMessagesList, Message.timestamp, Message.content);
				else {
					if (UserColor == "black") {
						WhiteTimer = Message.async;
						UpdateTimer("right-side", FormatMilliseconds(WhiteTimer));
					}
					else {
						BlackTimer = Message.async;
						UpdateTimer("left-side", FormatMilliseconds(BlackTimer));
					}
					SwitchingDrop(Message.x, Message.y);
					LastTimestamp = new Date().getTime();
					ResumeChessboard();

					let Winner = WinnerCheck(Message.x, Message.y);
					if (Winner != "None")
						GameOver(Winner);
				}
			}

			$(".review-chessboard-button").mousedown(() => {
				$(".popup-panel").removeClass("popup-panel-revealing");
				$(".popup-panel").addClass("popup-panel-hiding");
			});
			$(".review-chessboard-button").mouseup(() => {
				$(".popup-panel").removeClass("popup-panel-hiding");
				$(".popup-panel").addClass("popup-panel-revealing");
			});
			$(".review-chessboard-button").mouseleave(() => { $(".review-chessboard-button").mouseup(); });

			NewGameButton.onclick = () => { document.location = "matching.html"; };
			ReturnMainPageButton.onclick = () => { document.location = "main_page.html"; };

			$(".game-result-gamer-name").click((event) => {
				let UserID = event.target.getAttribute("user-id");
				document.location = `user_space.html?user_id=${UserID}`;
			});

			(function RejoinCheck() {
				let StartTime = 0;
				for (let Attribute of window.location.href.split("?")[1].split("&"))
					if (Attribute.startsWith("start_time="))
						StartTime = parseInt(Attribute.slice(11));
				if (new Date().getTime() - StartTime > 5000)
					window.location = "main_page.html";
			})();
		</script>
	</body>
</html>
